package com.jianbing.ssl;

import com.jianbing.util.PropertiesUtils;
import com.jianbing.util.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.net.ssl.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.util.Arrays;

/**
 * Created by Han, Tixiang on 2016/9/11 0011.
 */
public class SSLContextProvider {
    private static Log log = LogFactory.getLog(SSLContextProvider.class);
    /**
     * open ssl的证书文件和RSA秘钥先通过工具转化为java能够识别的格式
     * openssl pkcs12 -export -clcerts -in zhengshu.crt -inkey key.key -out server.p12
     * 执行openssl需要输入密码，这个密码在就是本程序中需要的密码
     *
     * @return
     */
    public static SSLContext getOpensslContextByP12Format() {
        try {
            String file = PropertiesUtils.getProperties("keyName"); // "c:/server.p12";
            String keyType = "PKCS12";
            char[] password = PropertiesUtils.getProperties("keyPwd").toCharArray();
            KeyStore ks = KeyStore.getInstance(keyType);
            ks.load(new FileInputStream(file), password);
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(
                    KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, password);
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(kmf.getKeyManagers(), null, null);
            return ctx;
        } catch (Exception e) {
            log.error(e.toString(),e);
        }
        return null;
    }

    /**
     * 公共调用方法
     * @return
     */
    public static SSLContext getSSLContext() {
        String file = PropertiesUtils.getProperties("keyName"); // "c:/server.p12";
        if (StringUtils.isEmpty(file)) {
            return null;
        }
        if (file.endsWith(".jks")) {
            return getSSLContextByJksFormat();
        } else if (file.endsWith(".p12")) {
            return getOpensslContextByP12Format();
        }
        return null;
}

    /**
     * keytool -genkey -alias securechat -keysize 2048 -validity 365 -keyalg RSA -dname "CN=kaifa.jianbing.com" -keypass sNetty -storepass sNetty -keystore sChat.jks
     * -keystore 指定密钥库的名称
     * -keypass 指定别名条目的密码(私钥的密码)
     * java jks格式
     *
     * @return
     */
    public static SSLContext getSSLContextByJksFormat() {
        InputStream in = null;
        String keyName = PropertiesUtils.getProperties("keyName"); //sChat.jks
        char[] keyPwd = PropertiesUtils.getProperties("keyPwd").toCharArray();
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            in = new FileInputStream(new File(keyName));
            //in = SSLContextProvider.class.getClassLoader().getResourceAsStream(keyName)
            keyStore.load(in, keyPwd);
            // 初始化key manager factory
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
                    .getDefaultAlgorithm());
            kmf.init(keyStore, keyPwd);
            // 初始化ssl context
            SSLContext context = SSLContext.getInstance("SSL");
         /*   context.init(kmf.getKeyManagers(),
                    new TrustManager[] { new MyX509TrustManager() },
                    new SecureRandom());*/
            context.init(kmf.getKeyManagers(), null, null);
            return context;
        } catch (Exception e) {
            log.error(e.toString(),e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }

        }

        return null;
    }

    public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException {
        X509TrustManager x509m = new X509TrustManager() {
            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
            }

            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        // 获取一个SSLContext实例
        SSLContext s = SSLContext.getInstance("SSL");
        // 初始化SSLContext实例
        s.init(null, new TrustManager[]{x509m},
                new java.security.SecureRandom());
        // 打印这个SSLContext实例使用的协议
        System.out.println("缺省安全套接字使用的协议: " + s.getProtocol());
        // 获取SSLContext实例相关的SSLEngine
        SSLEngine e = s.createSSLEngine();
        System.out
                .println("支持的协议: " + Arrays.asList(e.getSupportedProtocols()));
        System.out.println("启用的协议: " + Arrays.asList(e.getEnabledProtocols()));
        System.out.println("支持的加密套件: "
                + Arrays.asList(e.getSupportedCipherSuites()));
        System.out.println("启用的加密套件: "
                + Arrays.asList(e.getEnabledCipherSuites()));
    }
}
